using BunnyEater.Domain.Base;
using Microsoft.EntityFrameworkCore;
using System.Linq.Expressions;

namespace BunnyEater.Repository.Extensions
{
    /// <summary>
    /// 分页查询扩展方法
    /// </summary>
    public static class PagedQueryExtensions
    {
        /// <summary>
        /// 对IQueryable进行分页查询
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="query">查询源</param>
        /// <param name="pageIndex">页码（从1开始）</param>
        /// <param name="pageSize">每页大小</param>
        /// <param name="predicate">查询条件</param>
        /// <param name="orderBy">排序表达式</param>
        /// <param name="isAscending">是否升序</param>
        /// <returns>分页结果</returns>
        public static async Task<Page<T>> ToPagedListAsync<T>(
            this IQueryable<T> query,
            int pageIndex,
            int pageSize,
            Expression<Func<T, bool>>? predicate = null,
            Expression<Func<T, object>>? orderBy = null,
            bool isAscending = true) where T : class
        {
            // 参数验证
            if (pageIndex < 1) pageIndex = 1;
            if (pageSize < 1) pageSize = 10;

            // 应用查询条件
            if (predicate != null)
            {
                query = query.Where(predicate);
            }

            // 获取总记录数
            int totalItems = await query.CountAsync();

            // 应用排序
            if (orderBy != null)
            {
                query = isAscending ? query.OrderBy(orderBy) : query.OrderByDescending(orderBy);
            }

            // 应用分页
            var items = await query
                .Skip((pageIndex - 1) * pageSize)
                .Take(pageSize)
                .ToListAsync();

            // 计算总页数
            int totalPages = (int)Math.Ceiling((double)totalItems / pageSize);

            // 返回分页结果
            return new Page<T>
            {
                Items = items,
                PageNumber = pageIndex,
                PageSize = pageSize,
                TotalPages = totalPages,
                TotalItems = totalItems
            };
        }

        /// <summary>
        /// 对IQueryable进行分页查询（支持复杂排序）
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="query">查询源</param>
        /// <param name="pageIndex">页码（从1开始）</param>
        /// <param name="pageSize">每页大小</param>
        /// <param name="predicate">查询条件</param>
        /// <param name="orderBy">排序表达式</param>
        /// <returns>分页结果</returns>
        public static async Task<Page<T>> ToPagedListAsync<T>(
            this IQueryable<T> query,
            int pageIndex,
            int pageSize,
            Expression<Func<T, bool>>? predicate = null,
            Func<IQueryable<T>, IOrderedQueryable<T>>? orderBy = null) where T : class
        {
            // 参数验证
            if (pageIndex < 1) pageIndex = 1;
            if (pageSize < 1) pageSize = 10;

            // 应用查询条件
            if (predicate != null)
            {
                query = query.Where(predicate);
            }

            // 获取总记录数
            int totalItems = await query.CountAsync();

            // 应用排序
            if (orderBy != null)
            {
                query = orderBy(query);
            }

            // 应用分页
            var items = await query
                .Skip((pageIndex - 1) * pageSize)
                .Take(pageSize)
                .ToListAsync();

            // 计算总页数
            int totalPages = (int)Math.Ceiling((double)totalItems / pageSize);

            // 返回分页结果
            return new Page<T>
            {
                Items = items,
                PageNumber = pageIndex,
                PageSize = pageSize,
                TotalPages = totalPages,
                TotalItems = totalItems
            };
        }

        /// <summary>
        /// 对IQueryable进行分页查询（支持多字段排序）
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="query">查询源</param>
        /// <param name="pageIndex">页码（从1开始）</param>
        /// <param name="pageSize">每页大小</param>
        /// <param name="predicate">查询条件</param>
        /// <param name="sortFields">排序字段列表</param>
        /// <returns>分页结果</returns>
        public static async Task<Page<T>> ToPagedListAsync<T>(
            this IQueryable<T> query,
            int pageIndex,
            int pageSize,
            Expression<Func<T, bool>>? predicate = null,
            params (Expression<Func<T, object>> field, bool isAscending)[] sortFields) where T : class
        {
            // 参数验证
            if (pageIndex < 1) pageIndex = 1;
            if (pageSize < 1) pageSize = 10;

            // 应用查询条件
            if (predicate != null)
            {
                query = query.Where(predicate);
            }

            // 获取总记录数
            int totalItems = await query.CountAsync();

            // 应用多字段排序
            if (sortFields != null && sortFields.Length > 0)
            {
                IOrderedQueryable<T>? orderedQuery = null;
                for (int i = 0; i < sortFields.Length; i++)
                {
                    var (field, isAscending) = sortFields[i];
                    if (i == 0)
                    {
                        orderedQuery = isAscending ? query.OrderBy(field) : query.OrderByDescending(field);
                    }
                    else
                    {
                        orderedQuery = isAscending ? orderedQuery!.ThenBy(field) : orderedQuery!.ThenByDescending(field);
                    }
                }
                query = orderedQuery ?? query;
            }

            // 应用分页
            var items = await query
                .Skip((pageIndex - 1) * pageSize)
                .Take(pageSize)
                .ToListAsync();

            // 计算总页数
            int totalPages = (int)Math.Ceiling((double)totalItems / pageSize);

            // 返回分页结果
            return new Page<T>
            {
                Items = items,
                PageNumber = pageIndex,
                PageSize = pageSize,
                TotalPages = totalPages,
                TotalItems = totalItems
            };
        }
    }
}